<script setup>
import { ref, nextTick } from 'vue'
import { Delete, Plus } from '@element-plus/icons-vue'
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import { dishPublishService, dishGetDetailService } from '@/api/article'
import { labelGetListService, labelCountService } from '@/api/label.js'
import { materialGetListService, materialCountService } from '@/api/material.js'
import { uploadService } from '@/api/file.js'

// 控制抽屉显示隐藏
const visibleDrawer = ref(false)

// 默认数据
const defaultForm = {
  id: '',
  dishName: '', // 标题
  price: '', // 价格
  introduce: '', // 简介
  practice: '',
  labels: [],
  materials: [],
  urls: [] // 封面图片 url 路径
}
// 准备数据
const formModel = ref({
  ...defaultForm,
  labels: JSON.parse(JSON.stringify(defaultForm.labels)),
  materials: JSON.parse(JSON.stringify(defaultForm.materials)),
  urls: JSON.parse(JSON.stringify(defaultForm.urls))
})

const imgFileList = ref([])
const onSelectFile = async (uploadFile, list) => {
  // 提交图片
  const fd = new FormData()
  fd.append('file', uploadFile.raw)
  const res = await uploadService(fd)

  imgFileList.value.push({ url: res.data.data })
  console.log(list)
}

// 标签选择
const labelQueryParams = ref({
  current: 1, // 当前页
  size: 10 // 当前生效的每页条数
  // name: '' // 查询关键词
})
const labelInputVisible = ref(false) // 输入框是否显示
const labelInputValue = ref('') // 选项的value
const saveTagInput = ref(null) // input 的 DOM
const allLabels = ref([]) // 全部标签
const labelsChoice = ref([]) // 输入关键词后的搜索结果
const labelLoading = ref(false) // 单选框远程搜索时的加载状态
// 点击按钮 展示单选框，查询所有标签
const labelShowInput = async () => {
  labelInputVisible.value = true
  nextTick(() => {
    saveTagInput.value.focus()
  })
  const countRes = await labelCountService()
  labelQueryParams.value.size = countRes.data.data
  const res = await labelGetListService(labelQueryParams.value)
  allLabels.value = res.data.data.rows
}
// 删除标签
const labelHandleClose = async (tagId) => {
  formModel.value.labels = formModel.value.labels.filter((item) => {
    return item.id != tagId
  })
}
// 远程搜索方法
const labelRemoteMethod = async (query) => {
  if (query !== '' && query !== null) {
    labelLoading.value = true
    setTimeout(() => {
      labelLoading.value = false
      labelsChoice.value = allLabels.value.filter((item) => {
        return item.labelName.toLowerCase().indexOf(query.toLowerCase()) > -1
      })
    }, 200)
  } else {
    labelsChoice.value = []
  }
}
// 选择器按下回车，tag+1
const labelHandleEnter = () => {
  if (labelInputValue.value !== null) {
    allLabels.value.some((item) => {
      if (item.id === labelInputValue.value) {
        formModel.value.labels.push(item)
        return true
      }
    })
    labelInputValue.value = ''
    labelInputVisible.value = false
  }
}
// 已经选择的标签状态应该为禁选
const labelDisabled = (itemId) => {
  return !formModel.value.labels.every((item) => item.id !== itemId)
}
// 选择器失去焦点，变回按钮
const labelBlur = () => {
  labelInputValue.value = ''
  labelInputVisible.value = false
}

const materialQueryParams = ref({
  current: 1, // 当前页
  size: 10 // 当前生效的每页条数
  // name: '' // 查询关键词
})
const materialInputVisible = ref(false) // 输入框是否显示
const materialInputValue = ref('') // 选项的value
const materialTagInput = ref(null) // input 的 DOM
const allMaterial = ref([]) // 全部材料
const materialChoice = ref([]) // 输入关键词后的搜索结果
const materialLoading = ref(false) // 单选框远程搜索时的加载状态
// 材料选择
const materialShowInput = async () => {
  materialInputVisible.value = true
  nextTick(() => {
    materialTagInput.value.focus()
  })
  const countRes = await materialCountService()
  materialQueryParams.value.size = countRes.data.data
  const res = await materialGetListService(materialQueryParams.value)
  allMaterial.value = res.data.data.rows
}
// 删除材料
const materialHandleClose = async (tagId) => {
  formModel.value.materials = formModel.value.materials.filter((item) => {
    return item.id != tagId
  })
}
// 远程搜索方法
const materialRemoteMethod = async (query) => {
  if (query !== '' && query !== null) {
    materialLoading.value = true
    setTimeout(() => {
      materialLoading.value = false
      materialChoice.value = allMaterial.value.filter((item) => {
        return item.materialName.toLowerCase().indexOf(query.toLowerCase()) > -1
      })
    }, 200)
  } else {
    materialChoice.value = []
  }
}
// 选择器按下回车，tag+1
const materialHandleEnter = () => {
  if (materialInputValue.value !== null) {
    allMaterial.value.some((item) => {
      if (item.id === materialInputValue.value) {
        formModel.value.materials.push(item)
        return true
      }
    })
    materialInputValue.value = ''
    materialInputVisible.value = false
  }
}
// 已经选择的材料状态应该为禁选
const materialDisabled = (itemId) => {
  return !formModel.value.materials.every((item) => item.id !== itemId)
}
// 选择器失去焦点，变回按钮
const materialBlur = () => {
  materialInputValue.value = ''
  materialInputVisible.value = false
}

// 选择材料用量
// const weightInputVisible = ref(false)
const weightIdOnChange = ref('')
const weightInputValue = ref('')
const weightTagInput = ref(null)
const weightShowInput = (id, weight) => {
  weightIdOnChange.value = id
  weightInputValue.value = weight
  nextTick(() => {
    weightTagInput.value.focus()
  })
}
// 选择器按下回车，tag+1
const weightHandleEnter = (id) => {
  if (weightInputValue.value !== null && weightInputValue.value !== '') {
    formModel.value.materials.some((item) => {
      if (item.id === id) {
        item.weight = weightInputValue.value
        return true
      }
    })
    weightInputValue.value = ''
    weightIdOnChange.value = ''
  }
}
// 选择器失去焦点，变回按钮
const weightBlur = () => {
  weightIdOnChange.value = ''
  weightInputValue.value = ''
}

// 提交
const emit = defineEmits(['success'])
const onPublish = async () => {
  formModel.value.urls = []
  imgFileList.value.forEach((item) => {
    formModel.value.urls.push(item.url)
  })

  // 发请求
  if (formModel.value.id) {
    // 编辑操作
    await dishPublishService(formModel.value)
    ElMessage.success('修改成功')
    visibleDrawer.value = false
    emit('success', 'edit')
  } else {
    // 添加操作
    await dishPublishService(formModel.value)
    ElMessage.success('添加成功')
    visibleDrawer.value = false
    // 通知到父组件，添加成功了
    emit('success', 'add')
  }
}

const handleDrawerClose = async () => {
  imgFileList.value = []
}

// 组件对外暴露一个方法 open，基于open传来的参数，区分添加还是编辑
// open({})  => 表单无需渲染，说明是添加
// open({ id, ..., ... })  => 表单需要渲染，说明是编辑
// open调用后，可以打开抽屉
const introduceEditorRef = ref(null)
const practiceEditorRef = ref(null)
const open = async (row) => {
  visibleDrawer.value = true // 显示抽屉
  // 基于默认的数据，重置form数据
  formModel.value = {
    ...defaultForm,
    labels: JSON.parse(JSON.stringify(defaultForm.labels)),
    materials: JSON.parse(JSON.stringify(defaultForm.materials)),
    urls: JSON.parse(JSON.stringify(defaultForm.urls))
  }
  // 这里重置了表单的数据，但是图片上传img地址，富文本编辑器内容 => 需要手动重置
  imgFileList.value = []

  if (row.id) {
    // 需要基于 row.id 发送请求，获取编辑对应的详情数据，进行回显
    const res = await dishGetDetailService(row.id)
    for (let key in formModel.value) {
      if (res.data.data[key]) {
        formModel.value[key] = res.data.data[key]
      }
    }
    // 图片需要单独处理回显
    const images = formModel.value.urls
    images.forEach((item) => {
      imgFileList.value.push({ url: item })
    })
  } else {
    nextTick(() => {
      introduceEditorRef.value.setHTML('')
      practiceEditorRef.value.setHTML('')
    })
  }
}

defineExpose({
  open
})
</script>

<template>
  <el-drawer
    v-model="visibleDrawer"
    :title="formModel.id ? '编辑菜品' : '添加菜品'"
    direction="rtl"
    size="50%"
    @close="handleDrawerClose"
  >
    <!-- 发表菜品表单 -->
    <el-form :model="formModel" ref="formRef" label-width="100px">
      <el-form-item label="菜品标题" prop="dishName">
        <el-input
          v-model="formModel.dishName"
          placeholder="请输入标题"
        ></el-input>
      </el-form-item>
      <el-form-item label="菜品价格" prop="price">
        <el-input
          disabled
          v-model="formModel.price"
          placeholder="价格"
        ></el-input>
      </el-form-item>
      <el-form-item label="菜品封面" prop="urls">
        <el-upload
          :file-list="imgFileList"
          :limit="5"
          list-type="picture-card"
          class="avatar-uploader"
          :show-file-list="true"
          :auto-upload="false"
          :on-change="onSelectFile"
        >
          <el-icon class="avatar-uploader-icon">
            <Plus />
          </el-icon>
        </el-upload>
      </el-form-item>
      <el-form-item label="菜品简介" prop="introduce">
        <div class="editor">
          <quill-editor
            ref="introduceEditorRef"
            v-model:content="formModel.introduce"
            content-type="text"
            theme="snow"
          ></quill-editor>
        </div>
      </el-form-item>
      <el-form-item label="推荐做法" prop="practice">
        <div class="editor">
          <quill-editor
            ref="practiceEditorRef"
            v-model:content="formModel.practice"
            content-type="text"
            theme="snow"
          ></quill-editor>
        </div>
      </el-form-item>
      <el-form-item label="相关标签" prop="labels">
        <el-tag
          :key="tag.id"
          v-for="tag in formModel.labels"
          closable
          :disable-transitions="false"
          @close="labelHandleClose(tag.id)"
        >
          {{ tag.labelName }}
        </el-tag>
        <el-select
          class="input-new-tag"
          v-model="labelInputValue"
          v-if="labelInputVisible"
          ref="saveTagInput"
          size="small"
          filterable
          remote
          reserve-keyword
          :remote-method="labelRemoteMethod"
          @keyup.enter="labelHandleEnter"
          :loading="labelLoading"
          @blur="labelBlur"
        >
          <el-option
            v-for="item in labelsChoice"
            :key="item.id"
            :label="item.labelName"
            :value="item.id"
            :disabled="labelDisabled(item.id)"
          >
          </el-option>
        </el-select>
        <el-button
          v-else
          class="button-new-tag"
          size="small"
          @click="labelShowInput"
        >
          + New Tag
        </el-button>
      </el-form-item>
      <el-form-item label="材料" prop="materials">
        <el-select
          class="input-new-tag"
          v-model="materialInputValue"
          v-if="materialInputVisible"
          ref="materialTagInput"
          size="small"
          filterable
          remote
          reserve-keyword
          :remote-method="materialRemoteMethod"
          @keyup.enter="materialHandleEnter"
          :loading="materialLoading"
          @blur="materialBlur"
        >
          <el-option
            v-for="item in materialChoice"
            :key="item.id"
            :label="item.materialName"
            :value="item.id"
            :disabled="materialDisabled(item.id)"
          >
            <span style="float: left">{{ item.materialName }}</span>
            <span style="float: right; color: #8492a6; font-size: 13px"
              >{{ item.price
              }}<span style="font-size: 10px">￥/500g</span></span
            >
          </el-option>
        </el-select>
        <el-button
          v-else
          circle
          plain
          type="success"
          :icon="Plus"
          @click="materialShowInput"
        ></el-button>
        <el-table :data="formModel.materials" style="width: 100%">
          <el-table-column label="名称" width="180">
            <template v-slot="scope">
              <span style="margin-left: 10px">{{
                scope.row.materialName
              }}</span>
            </template>
          </el-table-column>
          <el-table-column label="价格（￥/500g）" width="180">
            <template v-slot="scope">
              <span style="margin-left: 10px">{{ scope.row.price }}</span>
            </template>
          </el-table-column>
          <el-table-column label="用量（500g）" width="180">
            <template v-slot="scope">
              <el-input
                ref="weightTagInput"
                v-if="scope.row.id === weightIdOnChange"
                v-model="weightInputValue"
                placeholder="请输入材料用量"
                @keyup.enter="weightHandleEnter(scope.row.id)"
                @blur="weightBlur"
              ></el-input>
              <span
                v-else
                style="
                  margin-left: 10px;
                  display: inline-block;
                  width: 100%;
                  height: 100%;
                "
                @click="weightShowInput(scope.row.id, scope.row.weight)"
                >{{ scope.row.weight }}</span
              >
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template v-slot="scope">
              <el-button
                class="material-del-button"
                plain
                type="danger"
                :icon="Delete"
                @click="materialHandleClose(scope.row.id)"
              >
                <!-- @click="handleDelete(scope.$index, scope.row)" -->
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <el-form-item>
        <el-button @click="onPublish('已发布')" type="primary">发布</el-button>
      </el-form-item>
    </el-form>
  </el-drawer>
</template>

<style lang="scss" scoped>
.avatar-uploader {
  :deep() {
    .avatar {
      width: 178px;
      height: 178px;
      display: block;
    }

    .el-upload {
      border: 1px dashed var(--el-border-color);
      border-radius: 6px;
      cursor: pointer;
      position: relative;
      overflow: hidden;
      transition: var(--el-transition-duration-fast);
    }

    .el-upload:hover {
      border-color: var(--el-color-primary);
    }

    .el-icon.avatar-uploader-icon {
      font-size: 28px;
      color: #8c939d;
      width: 178px;
      height: 178px;
      text-align: center;
    }
  }
}

.el-tag + .el-tag {
  margin-left: 10px;
  height: 32px;
}

.button-new-tag {
  margin-left: 10px;
  height: 32px;
  line-height: 30px;
  padding-top: 0;
  padding-bottom: 0;
}

.input-new-tag {
  width: 90px;
  margin-left: 10px;
  vertical-align: bottom;
  height: 32px;
}

.editor {
  width: 100%;

  :deep(.ql-editor) {
    min-height: 200px;
  }
}

.material-del-button {
  height: 28px;
  width: 60px;
}
</style>
